﻿' ----------------------------------------------------------------------------------
' Microsoft Developer & Platform Evangelism
' 
' Copyright (c) Microsoft Corporation. All rights reserved.
' 
' THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
' EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES 
' OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ----------------------------------------------------------------------------------
' The example companies, organizations, products, domain names,
' e-mail addresses, logos, people, places, and events depicted
' herein are fictitious.  No association with any real company,
' organization, product, domain name, email address, logo, person,
' places, or events is intended or should be inferred.
' ----------------------------------------------------------------------------------

Imports Microsoft.Samples.WindowsPhoneCloud.Phone.Push
Imports Microsoft.Phone.Notification
Imports System.Windows.Threading
Imports System.IO
Imports System.Collections.ObjectModel
Imports System.Globalization

Namespace ViewModel

    Public Class NotificationsPageViewModel
        Inherits PivotItemViewModel
        Private Const IconsRootUri As String = "/Toolkit.Content/"

        Private ReadOnly dispatcher As Dispatcher
        Private ReadOnly pushNotificationClient As ISamplePushUserRegistrationClient

        Private messageValue As String
        Private canEnableOrDisablePushValue As Boolean = True

        Public Sub New()
            Me.New(App.CloudClientFactory.ResolvePushNotificationClient(), Deployment.Current.Dispatcher)
        End Sub

        Public Sub New(ByVal pushNotificationClient As ISamplePushUserRegistrationClient, ByVal dispatcher As Dispatcher)
            Me.pushNotificationClient = pushNotificationClient
            Me.dispatcher = dispatcher
            Me.Notifications = New ObservableCollection(Of String)()

            AddHandler PushContext.Current.RawNotification, AddressOf Me.OnRawNotification
            AddHandler PushContext.Current.PropertyChanged, Sub(s, e)
                                                                If e.PropertyName.Equals("IsConnected", StringComparison.OrdinalIgnoreCase) Then
                                                                    Me.NotifyPropertyChanged("ConnectionStatus")
                                                                End If
                                                            End Sub
        End Sub

        Public Event PushNotificationServiceException As EventHandler(Of EventArgs(Of String))

        Public Event BeginPushConnection As EventHandler(Of EventArgs)

        Public Event EndPushConnection As EventHandler(Of EventArgs)

        Public Property IsPushEnabled() As Boolean
            Get
                Return PushContext.Current.IsPushEnabled
            End Get

            Set(ByVal value As Boolean)
                If PushContext.Current.IsPushEnabled <> value Then
                    Me.CanEnableOrDisablePush = False
                    PushContext.Current.IsPushEnabled = value

                    If PushContext.Current.IsPushEnabled Then
                        Me.ConnectToPushNotificationService()
                    Else
                        Me.DisconnectFromPushNotificationService()
                    End If

                    Me.NotifyPropertyChanged("IsPushEnabled")
                End If
            End Set
        End Property

        Public Property CanEnableOrDisablePush() As Boolean
            Get
                Return Me.canEnableOrDisablePushValue
            End Get

            Set(ByVal value As Boolean)
                If Me.canEnableOrDisablePushValue <> value Then
                    Me.canEnableOrDisablePushValue = value
                    Me.NotifyPropertyChanged("CanEnableOrDisablePush")
                End If
            End Set
        End Property

        Public ReadOnly Property ConnectionStatus() As String
            Get
                Return If(PushContext.Current.IsConnected, "Connected", "Disconnected")
            End Get
        End Property

        Public Property Message() As String
            Get
                Return Me.messageValue
            End Get

            Set(ByVal value As String)
                If Me.messageValue <> value Then
                    Me.messageValue = value
                    Me.NotifyPropertyChanged("Message")
                End If
            End Set
        End Property

        Public Property Notifications() As ObservableCollection(Of String)

        Sub ShowError(sender As Object, e As EventArgs(Of String))
            MessageBox.Show(e.Value, "Push Notification Error", MessageBoxButton.OK)
            Throw New NotImplementedException
        End Sub


        Public Sub GetNotificationUpdates()
            Me.Message = "Getting last notification updates..."

            Me.pushNotificationClient.GetUpdates(
                Sub(r)
                    Me.dispatcher.BeginInvoke(
                        Sub()
                            If r.Exception Is Nothing Then
                                For Each m In r.Response
                                    Me.Notifications.Insert(0, m)
                                Next m
                                Me.Message = String.Format(CultureInfo.InvariantCulture, "Notification updates received at {0}.", Date.Now.ToLongTimeString())
                            Else
                                Me.Message = r.Exception.Message
                            End If

                            Me.CanEnableOrDisablePush = True
                            Me.RaiseEndPushConnection()
                        End Sub)
                End Sub)
        End Sub

        Public Sub ConnectToPushNotificationService()
            Me.Message = "Registering with Push Notification Service..."
            Me.CanEnableOrDisablePush = False
            Me.RaiseBeginPushConnection()

            Me.pushNotificationClient.Connect(
                Sub(r)
                    Me.dispatcher.BeginInvoke(
                        Sub()
                            If r.Exception Is Nothing Then
                                Me.GetNotificationUpdates()
                            Else
                                Me.Message = "Error connecting from Push Notification Service."
                                Me.CanEnableOrDisablePush = True

                                Me.RaisePushNotificationServiceException(r.Exception.Message)
                                Me.RaiseEndPushConnection()
                            End If
                        End Sub)
                End Sub)
        End Sub

        Public Sub DisconnectFromPushNotificationService()
            Me.RaiseBeginPushConnection()

            Me.pushNotificationClient.Disconnect(
                Sub(r)
                    Me.dispatcher.BeginInvoke(
                        Sub()
                            If r.Exception Is Nothing Then
                                Me.Message = "Disconnected from Push Notification Service."
                            Else
                                Me.Message = "Error disconnecting from Push Notification Service."
                                Me.RaisePushNotificationServiceException(r.Exception.Message)
                            End If
                            Me.CanEnableOrDisablePush = True
                            Me.RaiseEndPushConnection()
                        End Sub)
                End Sub)
        End Sub

        Protected Overrides Sub PopulateApplicationBarButtons(ByVal applicationBar As IApplicationBar)
            Dim clearMessagesButton = New ApplicationBarIconButton(New Uri(String.Format("{0}{1}", IconsRootUri, "appbar.delete.rest.png"), UriKind.Relative)) With {.Text = "clear"}
            AddHandler clearMessagesButton.Click, Sub(s, e) Me.Notifications.Clear()

            applicationBar.Buttons.Add(clearMessagesButton)
        End Sub

        Private Sub OnRawNotification(ByVal sender As Object, ByVal e As HttpNotificationEventArgs)
            Try
                e.Notification.Body.Position = 0

                Dim stream = New StreamReader(e.Notification.Body)
                Dim rawMessage = stream.ReadToEnd()
                Me.Notifications.Insert(0, rawMessage)

                Me.Message = String.Format(CultureInfo.InvariantCulture, "Push notification received at {0}.", Date.Now.ToLongTimeString())
            Catch exception As Exception
                Me.Message = String.Format(CultureInfo.InvariantCulture, "There was an error receiving last push notification: {0}", exception.Message)
            End Try
        End Sub

        Private Sub RaisePushNotificationServiceException(ByVal errorMessage As String)
            RaiseEvent PushNotificationServiceException(Me, New EventArgs(Of String)(errorMessage))
        End Sub

        Private Sub RaiseBeginPushConnection()
            RaiseEvent BeginPushConnection(Me, EventArgs.Empty)
        End Sub

        Private Sub RaiseEndPushConnection()
            RaiseEvent EndPushConnection(Me, EventArgs.Empty)
        End Sub

        Sub CleanPushNotificationServiceException()
            RemoveHandler Me.PushNotificationServiceException, AddressOf Me.ShowError
        End Sub

    End Class
End Namespace